C++实现读写ini配置文件 您所在的位置:网站首页 c++ ini读写 C++实现读写ini配置文件

C++实现读写ini配置文件

2024-01-08 02:56| 来源: 网络整理| 查看: 265

配置文件的读取是每个程序必备的功能,配置文件的格式多种多样,例如:ini格式、json格式、xml格式等。其中属ini格式最为简单,且应用广泛。

1.概述

配置文件的读取是每个程序必备的功能,配置文件的格式多种多样,例如:ini格式、json格式、xml格式等。其中属ini格式最为简单,且应用广泛。

2.ini格式语法

注释内容采用“#”或者“;”开头。

配置是由一系列的section组成,每个section就是一个关联的配置块,section使用[]包含起来。

每个section下配置的是具体的配置项,每个配置项是使用“=”分隔的key-value对。

下面让我们来看一个简单的示例,假设我们有一个配置文件demo.cfg,它的内容如下所示。

[server] ip = 127.0.0.1 port = 8088

上面的配置内容中,有一个server的配置节,在这个配置节里有两个配置项,它们分别是ip和port,ip的值为127.0.0.1,port的值为8088。

3.配置读取

知道了ini格式语法之后,就可以根据语法规则来读取配置文件内容了,春哥这里实现了一个非常精简易用的版本,源代码文件config.hpp的内容如下。

#pragma once #include #include #include #include namespace Config { class Ini { public: void Dump(std::function deal) { auto iter = cfg_.begin(); while (iter != cfg_.end()) { auto kv_iter = iter->second.begin(); while (kv_iter != iter->second.end()) { deal(iter->first, kv_iter->first, kv_iter->second); ++kv_iter; } ++iter; } } bool Load(std::string file_name) { if (file_name == "") return false; std::ifstream in; std::string line; in.open(file_name.c_str()); if (not in.is_open()) return false; while (getline(in, line)) { std::string section, key, value; if (not parseLine(line, section, key, value)) { continue; } setSectionKeyValue(section, key, value); } return true; } void GetStrValue(const std::string& section, const std::string& key, std::string& value, std::string default_value) { value = default_value; if (cfg_.find(section) == cfg_.end()) { return; } if (cfg_[section].find(key) == cfg_[section].end()) { return; } value = cfg_[section][key]; } void GetIntValue(const std::string& section, const std::string& key, int64_t& value, int64_t default_value) { value = default_value; if (cfg_.find(section) == cfg_.end()) { return; } if (cfg_[section].find(key) == cfg_[section].end()) { return; } value = atol(cfg_[section][key].c_str()); } private: void ltrim(std::string& str) { if (str.empty()) return; size_t len = 0; char* temp = (char*)str.c_str(); while (*temp && isblank(*temp)) { ++len; ++temp; } if (len > 0) str.erase(0, len); } void rtrim(std::string& str) { if (str.empty()) return; size_t len = str.length(); size_t pos = len; while (pos > 0) { if (not isblank(str[pos - 1])) { break; } --pos; } if (pos != len) str.erase(pos); } void trim(std::string& str) { ltrim(str); rtrim(str); } void setSectionKeyValue(std::string& section, std::string& key, std::string& value) { if (cfg_.find(section) == cfg_.end()) { std::unordered_map kv_map; cfg_[section] = kv_map; } if (key != "" && value != "") cfg_[section][key] = value; } bool parseLine(std::string& line, std::string& section, std::string& key, std::string& value) { static std::string cur_section = ""; std::string nodes[2] = {"#", ";"}; //去掉注释的内容 for (int i = 0; i < 2; ++i) { std::string::size_type pos = line.find(nodes[i]); if (pos != std::string::npos) line.erase(pos); } trim(line); if (line == "") return false; if (line[0] == '[' && line[line.size() - 1] == ']') { section = line.substr(1, line.size() - 2); trim(section); cur_section = section; return false; } if (cur_section == "") return false; bool is_key = true; for (size_t i = 0; i < line.size(); ++i) { if (line[i] == '=') { is_key = false; continue; } if (is_key) { key += line[i]; } else { value += line[i]; } } section = cur_section; trim(key); trim(value); return true; } private: std::unordered_map cfg_; }; // ini格式配置文件的读取 } // namespace Config

Config命名空间下实现了Ini配置读取类。Load函数用于加载配置文件内容,GetStrValue函数和GetIntValue函数用于获取配置项值并支持设置默认值,Dump函数用于遍历配置文件的内容。由于在解析过程中需要删除字符串中的前导和后导空白符,因此我们还实现了trim函数用于删除前导和后导空白符。

这里重点讲解一下Load函数的逻辑:每次从配置文件中读取一行,然后先去掉注释的内容,接着再判断剩余的内容是一个section头配置,还是section下的key-value配置,再走不同的解析分支。

4.demo示例

以上面配置文件demo.cfg内容的读取为例,示例代码如下。

#include #include "config.hpp" int main(int argc, char *argv[]) { Config::Ini ini; ini.Load("./demo.cfg"); ini.Dump([](const std::string §ion, const std::string &key, const std::string value) { std::cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有